# 你可以选择使用单链表或者双链表，设计并实现自己的链表。 
# 
#  单链表中的节点应该具备两个属性：val 和 next 。val 是当前节点的值，next 是指向下一个节点的指针/引用。 
# 
#  如果是双向链表，则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。 
# 
#  实现 MyLinkedList 类： 
# 
#  
#  MyLinkedList() 初始化 MyLinkedList 对象。 
#  int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效，则返回 -1 。 
#  void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后，新节点会成为链表的第一个节点。 
#  void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。 
#  void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 
# index 等于链表的长度，那么该节点会被追加到链表的末尾。如果 index 比长度更大，该节点将 不会插入 到链表中。 
#  void deleteAtIndex(int index) 如果下标有效，则删除链表中下标为 index 的节点。 
#  
# 
#  
# 
#  示例： 
# 
#  
# 输入
# ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", 
# "deleteAtIndex", "get"]
# [[], [1], [3], [1, 2], [1], [1], [1]]
# 输出
# [null, null, null, null, 2, null, 3]
# 
# 解释
# MyLinkedList myLinkedList = new MyLinkedList();
# myLinkedList.addAtHead(1);
# myLinkedList.addAtTail(3);
# myLinkedList.addAtIndex(1, 2);    // 链表变为 1->2->3
# myLinkedList.get(1);              // 返回 2
# myLinkedList.deleteAtIndex(1);    // 现在，链表变为 1->3
# myLinkedList.get(1);              // 返回 3
#  
# 
#  
# 
#  提示： 
# 
#  
#  0 <= index, val <= 1000 
#  请不要使用内置的 LinkedList 库。 
#  调用 get、addAtHead、addAtTail、addAtIndex 和 deleteAtIndex 的次数不超过 2000 。 
#  
# 
#  Related Topics 设计 链表 👍 1082 👎 0


# leetcode submit region begin(Prohibit modification and deletion)
class Node:
    def __init__(self, val):
        self.val = val
        self.next = None


class MyLinkedList:
    """
    链表的索引是我们自己虚构的一个东西，实际上没有这个属性，我们自定义头节点后的第一个节点索引为0，依次类推
    如果我们要看一个节点得索引值是多少，例如从头节点后找i个节点就找到可目标节点，那么目标节点得索引值为i-1
    给节点定义index属性无意义，因为我们如果定义index属性，我们还是需要从头节点往后遍历看索引值是否符合值。那还不如直接从头节点往后数数
    size = index+1
    """

    def __init__(self):
        """
        单链表
        """
        self.size = 0
        self.head = Node(0)

    def get(self, index: int) -> int:
        if index <= self.size-1:
            cur = self.head
            # 头节点无index，第一个节点的index为0，第二个为2。即第i节点index就为i-1。那么我们要找到index个节点，我们就要从头节点开始往后数index个
            #
            for _ in range(index + 1):
                cur = cur.next
            return cur.val
        else:
            return -1

    def addAtHead(self, val: int) -> None:
        newnode = Node(val)
        self.size += 1
        newnode.next = self.head.next
        self.head.next = newnode
        # self.addAtIndex(0,val)

    def addAtTail(self, val: int) -> None:
        cur = self.head
        # 找到最后一个节点
        for _ in range(self.size):
            cur = cur.next

        cur.next = Node(val)
        self.size += 1
        # self.addAtIndex(self.size, val)
    def addAtIndex(self, index: int, val: int) -> None:
        # 注意此处不是>=。当index=self.size时，最后一个元素的索引即为size-1=index-1.那么最后一个元素就正好时要插入索引的前一个节点。
        # 所以当index=self.size时，元素直接插入链表最后
        if index > self.size:
            return
        # index若是为负数，则取0.此题目不用考虑
        # index = max(0,index)
        cur = self.head
        # 从头节点往后第index个节点他的索引即为index-1，也就是index的前一个索引
        for _ in range(index):
            cur = cur.next

        newnode = Node(val)
        newnode.next = cur.next
        cur.next = newnode
        #增加一个节点后 链表的长度+1
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        if index <= self.size - 1:
            cur = self.head
            # 找到要删除节点的上一个节点
            for _ in range(index):
                cur = cur.next
            cur.next = cur.next.next
            self.size -= 1

# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)
# leetcode submit region end(Prohibit modification and deletion)
